package com.hmdp.service.impl;

import com.hmdp.dto.Result;
import com.hmdp.entity.SeckillVoucher;
import com.hmdp.entity.VoucherOrder;
import com.hmdp.mapper.VoucherOrderMapper;
import com.hmdp.redis.SimpleRedisLock;
import com.hmdp.service.ISeckillVoucherService;
import com.hmdp.service.IVoucherOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmdp.redis.RedisIdWrok;
import com.hmdp.utils.UserHolder;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Service
@RequiredArgsConstructor
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {

    private  final ISeckillVoucherService seckillVoucherService;
    private  final RedisIdWrok redisIdWrok;
    private  final StringRedisTemplate stringRedisTemplate;
    /**
     * 生成秒杀券订单
     * @param voucherId
     * @return
     */
    @Override

    public Result seckillVoucher(Long voucherId) {
        //1.查询优惠券
        SeckillVoucher seckill = seckillVoucherService.getById(voucherId);
        //2.判断开始时间
        if (seckill.getBeginTime().isAfter(LocalDateTime.now())) {
            return Result.fail("抢购时间未开始");
        }
        //3.判断结束时间
        if (seckill.getEndTime().isBefore(LocalDateTime.now())) {
            return Result.fail("抢购时间已经结束");
        }
        //4.判断库存
        if (seckill.getStock() <=0) {
            return Result.fail("库存不足");
        }
        //生成订单
        Long userId = UserHolder.getUser().getId();
        //单机模式下synchronized锁
//
//        synchronized (userId.toString().intern()/*用户id作为锁对象*/){
//            IVoucherOrderService proxy = (IVoucherOrderService)AopContext.currentProxy();//为了确保creatVoucherOrder事务生效.获取代理对象
//            return proxy.creatVoucherOrder(voucherId);
//
//        }
        
        //集群模式下redis锁
        SimpleRedisLock lock = new SimpleRedisLock(stringRedisTemplate,"order");
        boolean success = lock.tryLock(1200L);
        if (!success ) {
            return Result.fail("只能一人下单");
        }
        try {
            IVoucherOrderService proxy = (IVoucherOrderService)AopContext.currentProxy();//为了确保creatVoucherOrder事务生效.获取代理对象
            return proxy.creatVoucherOrder(voucherId);
        } catch (IllegalStateException e) {
            throw new RuntimeException(e);
        } finally {

            lock.unlock();
        }

    }
    @Transactional
    public Result creatVoucherOrder(Long voucherId) {
        //解决一人只能买一单问题
        Long userId = UserHolder.getUser().getId();
        Integer count = lambdaQuery().eq(VoucherOrder::getUserId, userId)
                .eq(VoucherOrder::getVoucherId, voucherId)
                .count();
        if (count >0) {
            return Result.fail("不能重复购买");
        }
        //5.扣减库存
        boolean success = seckillVoucherService.update()
                .setSql("stock=stock-1")
                .eq("voucher_id", voucherId)
                .gt("stock",0) //乐观锁解决多线程扣库存问题
                .update();
        if (!success ) {
            return Result.fail("库存不足");
        }
        //6.生成订单
        VoucherOrder voucherOrder = new VoucherOrder();
        //6.1redis的唯一id
        VoucherOrder order = voucherOrder.setId(redisIdWrok.nextId("order"));
        //6.2userID
        voucherOrder.setUserId(userId);
        //6.2秒杀券ID
        voucherOrder.setVoucherId(voucherId);
        //6.3存入表中
        save(voucherOrder);
        return Result.ok(order.getVoucherId());
    }
}
